#ifndef __PARSER_H__
#define __PARSER_H__

#include <stdint.h>
#include "rarray.h"
#include "rstring.h"
#include "redobject.h"
#include "tokenizer.h"

/******************** type declatations ********************/

/* language structures */

typedef struct _if_t			if_t;
typedef struct _for_t			for_t;
typedef struct _try_t			try_t;
typedef struct _case_t			case_t;
typedef struct _while_t			while_t;
typedef struct _except_t		except_t;
typedef struct _switch_t		switch_t;
typedef struct _compond_t		compond_t;
typedef struct _function_t		function_t;

/* statements */

typedef struct _assign_t		assign_t;
typedef struct _delete_t		delete_t;
typedef struct _augment_t		augment_t;

/* control flows */

typedef struct _break_t			break_t;
typedef struct _return_t		return_t;
typedef struct _continue_t		continue_t;

/* generic statement */

typedef struct _statement_t		statement_t;

/* assign targets */

typedef struct _name_t			name_t;
typedef struct _attr_t			attr_t;
typedef struct _index_t			index_t;
typedef struct _invoke_t		invoke_t;
typedef struct _rvalue_t		rvalue_t;

/* expressions */

typedef struct _expr_t			expr_t;
typedef struct _unit_t			unit_t;
typedef struct _const_t			const_t;
typedef struct _range_t			range_t;

/******************** base type definations ********************/

typedef enum _node_type_t
{
	nt_if,
	nt_for,
	nt_try,
	nt_case,
	nt_while,
	nt_except,
	nt_switch,
	nt_compond,
	nt_function,

	nt_assign,
	nt_delete,
	nt_augment,

	nt_break,
	nt_return,
	nt_continue,

	nt_statement,

	nt_name,
	nt_attr,
	nt_index,
	nt_invoke,
	nt_rvalue,

	nt_expr,
	nt_unit,
	nt_const,
	nt_range,
} node_type_t;

typedef struct _node_base_t
{
	int			ref;
	node_type_t	type;
	int			lineno;
	int			position;
} node_base_t;

/* language structures */

typedef struct _if_t
{
	node_base_t		 node;
	expr_t			*expr;
	statement_t 	*pos;
	statement_t 	*neg;
} if_t;

typedef struct _for_t
{
	node_base_t		 node;
	statement_t		*init;
	expr_t			*condition;
	statement_t		*step;
	statement_t		*body;
} for_t;

typedef struct _try_t
{
	node_base_t		 node;
	statement_t		*body;
	rarray_t		 excepts;		// except_t
	statement_t		*finally;
	statement_t		*generic;
} try_t;

typedef struct _case_t
{
	node_base_t		 node;
	rarray_t		 ranges;		// range_t
	statement_t		*body;
} case_t;

typedef struct _while_t
{
	node_base_t		 node;
	expr_t			*expr;
	statement_t		*body;
} while_t;

typedef struct _except_t
{
	node_base_t		 node;
	statement_t		*body;
	rstring_t		*name;
	rarray_t		 types;			// rstring_t
} except_t;

typedef struct _switch_t
{
	node_base_t		 node;
	expr_t			*expr;
	statement_t		*other;
	rarray_t		 cases;			// case_t
} switch_t;

typedef struct _compond_t
{
	node_base_t		 node;
	rarray_t		 statements;	// statement_t
} compond_t;

typedef struct _function_t
{
	node_base_t		 node;
	rarray_t		 args;			// rstring_t
	rstring_t		*name;
	statement_t		*body;
	rstring_t		*vararg;
} function_t;

/* statements */

typedef enum _tv_type_t
{
	tv_attr,
	tv_name,
	tv_index,
} tv_type_t;

typedef struct _assign_t
{
	node_base_t		 node;
	tv_type_t		 type;
	expr_t			*expr;

	union
	{
		attr_t		*tv_attr;
		name_t		*tv_name;
		index_t		*tv_index;
	};
} assign_t;

typedef struct _delete_t
{
	node_base_t		 node;
	tv_type_t		 type;

	union
	{
		attr_t		*tv_attr;
		name_t		*tv_name;
		index_t		*tv_index;
	};
} delete_t;

typedef struct _augment_t
{
	node_base_t		 node;
	tv_type_t		 type;
	expr_t			*expr;
	rstring_t		*operator;

	union
	{
		attr_t		*tv_attr;
		name_t		*tv_name;
		index_t		*tv_index;
	};
} augment_t;

/* control flows */

typedef struct _break_t
{
	node_base_t		 node;
} break_t;

typedef struct _return_t
{
	node_base_t		 node;
	expr_t			*expr;
} return_t;

typedef struct _continue_t
{
	node_base_t		 node;
} continue_t;

/* generic statement */

typedef enum _st_type_t
{
	st_if,
	st_for,
	st_try,
	st_while,
	st_switch,
	st_compond,
	st_function,

	st_assign,
	st_delete,
	st_invoke,
	st_augment,

	st_break,
	st_return,
	st_continue,
} st_type_t;

typedef struct _statement_t
{
	node_base_t		 node;
	st_type_t		 type;

	union
	{
		if_t		*st_if;
		for_t		*st_for;
		try_t		*st_try;
		while_t		*st_while;
		switch_t	*st_switch;
		compond_t	*st_compond;
		function_t	*st_function;

		assign_t	*st_assign;
		delete_t	*st_delete;
		invoke_t	*st_invoke;
		augment_t	*st_augment;

		break_t		*st_break;
		return_t	*st_return;
		continue_t	*st_continue;
	};
} statement_t;

/* assign targets */

typedef struct _name_t
{
	node_base_t		 node;
	rstring_t		*name;
} name_t;

typedef struct _attr_t
{
	node_base_t		 node;
	rvalue_t		*value;
	rstring_t		*attribute;
} attr_t;

typedef struct _index_t
{
	node_base_t		 node;
	expr_t			*expr;
	rvalue_t		*value;
} index_t;

typedef struct _invoke_t
{
	node_base_t		 node;
	rarray_t		 args;			// expression_t
	rvalue_t		*value;
	rarray_t		 expand;		// char as void *
	char			 discard;
	char			 variable;
} invoke_t;

typedef enum _rv_type_t
{
	rv_attr,
	rv_name,
	rv_unit,
	rv_const,
	rv_index,
	rv_invoke,
} rv_type_t;

typedef struct _rvalue_t
{
	node_base_t		 node;
	rv_type_t		 type;

	union
	{
		attr_t		*rv_attr;
		name_t		*rv_name;
		unit_t		*rv_unit;
		const_t		*rv_const;
		index_t		*rv_index;
		invoke_t	*rv_invoke;
	};
} rvalue_t;

/* expressions */

typedef enum _e_type_t
{
	e_expr,
	e_rvalue,
} e_type_t;

typedef struct _expr_t
{
	node_base_t		 node;
	e_type_t		 el_type;
	e_type_t		 er_type;
	rstring_t		*operator;

	union
	{
		expr_t		*el_expr;
		rvalue_t	*el_rvalue;
	};

	union
	{
		expr_t		*er_expr;
		rvalue_t	*er_rvalue;
	};
} expr_t;

typedef enum _u_type_t
{
	u_expr,
	u_unit,
	u_rvalue,
	u_function,
} u_type_t;

typedef struct _unit_t
{
	node_base_t		 node;
	u_type_t		 type;
	rstring_t		*operator;

	union
	{
		expr_t		*u_expr;
		unit_t		*u_unit;
		rvalue_t	*u_rvalue;
		function_t	*u_function;
	};
} unit_t;

typedef enum _c_type_t
{
	c_int,
	c_float,
	c_string,
} c_type_t;

typedef struct _const_t
{
	node_base_t		 node;
	c_type_t		 type;

	union
	{
		int64_t		 c_int;
		float		 c_float;
		rstring_t	*c_string;
	};
} const_t;

typedef struct _range_t
{
	node_base_t		 node;
	expr_t			*begin;
	expr_t			*end;
} range_t;

/* parser types and functions */

typedef struct _parser_t
{
	RedObject	*consts;
	tokenizer_t *tokenizer;
	int			 nested_funcs;
	int			 nested_loops;
} parser_t;

RED_EXPORT void parser_free(parser_t *self);
RED_EXPORT void parser_init(parser_t *self, RedObject *consts, tokenizer_t *tokenizer);

RED_EXPORT compond_t *parser_parse(parser_t *self);

#endif /* __PARSER_H__ */
